﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Markup;
using Rhizome.Contract;
using Rhizome.Internal;

namespace Rhizome.Model
{
    [ContentProperty("Items")]
    public abstract class ItemsStateBase<TPlant, TItem> : StateBase<TPlant>, IForwardEvent, IStateInitialize, IStateActions
    {
        protected ItemsStateBase()
        {
            Items = new RhizomeElementCollection<TItem>(this);
        }

        public Collection<TItem> Items { get; private set; }

        #region IForwardEvent Members

        object IForwardEvent.GetForwardEvent()
        {
            return Items.GetForwardEvent();
        }

        #endregion

        #region IStateActions Members

        public void Initialize()
        {
            ForEach<IStateInitialize>(item => item.Initialize());
        }

        public void Cleanup()
        {
            ForEach<IStateInitialize>(item => item.Cleanup());
        }

        #endregion

        public void EntryAction()
        {
            ForEach<IStateActions>(item => item.EntryAction());
        }

        public void ExitAction()
        {
            ForEach<IStateActions>(item => item.ExitAction());
        }


        protected void ForEach(Action<TItem> action)
        {
            foreach (var item in Items)
                action(item);
        }


        protected void ForEach<T>(Action<T> action)
        {
            foreach (var item in Items.OfType<T>())
                action(item);
        }

        #region Overrides of RhizomeElement

        protected override IEnumerable<IEnumerable> GetElementCollections()
        {
            return base.GetElementCollections().Concat(new[] {Items});
        }

        #endregion
    }

    public abstract class ItemsStateBase<TPlant> : ItemsStateBase<TPlant, object>
    {
    }

    public abstract class ItemsStateBase : ItemsStateBase<object, object>
    {
    }
}